package com.hxh.generater.springBoot.simple.gen.crud;

import com.hxh.config.Constants;
import com.hxh.entity.Project;
import com.hxh.entity.ProjectTablePageConfig;
import com.hxh.entity.po.ClassInfo;
import com.hxh.entity.po.FieldName;
import com.hxh.generater.springBoot.util.ProcessWriteLine;
import com.hxh.generater.springBoot.util.methodParse.ParseJavaMethod;
import com.hxh.generater.springBoot.util.methodParse.entity.JavaClassMethod;
import com.hxh.util.GenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: AICode
 * @Package: com.hxh.generater
 * @ClassName: GenerationController
 * @Author: HXH
 * @Description:
 * @Date: 2023/11/28 15:08
 */
@Slf4j
public class GenController {

    private static String getCheckExist(ClassInfo classInfo) {
        String className = classInfo.getClassName();
        String serviceName = className + "Service";
        String serviceNameEntity = StringUtils.uncapitalize(serviceName);
        String classNameEntity = StringUtils.uncapitalize(className);

        StringBuilder checkExistStr = new StringBuilder("        " + className + " oldOne = " + serviceNameEntity + ".selectById(");
        StringBuilder params = new StringBuilder();
        StringBuilder failTips = new StringBuilder();

        for (FieldName fieldName : classInfo.getIdNameList()) {
            if (fieldName.isAutIncrement()) {
                //自动增长主键的，就不校验主键重复了
                return "";
            }
            params.append(classNameEntity).append(".get").append(StringUtils.capitalize(fieldName.getJavaName())).append("(),");
            failTips.append("\"").append(fieldName.getDesc()).append("：\" +").append(classNameEntity)
                    .append(".get").append(StringUtils.capitalize(fieldName.getJavaName())).append("()+\"，\"+");
        }
        if (params.length() > 0) {
            params.deleteCharAt(params.length() - 1);
            failTips.deleteCharAt(failTips.length() - 1);
            failTips.append("+ \"已存在！\"");
        }
        checkExistStr.append(params.toString()).append(");\n");
        checkExistStr.append("        if (oldOne != null) {\n");
        checkExistStr.append("            return ApiResult.fail(").append(failTips.toString()).append(");\n");
        checkExistStr.append("        }");
        return checkExistStr.toString();
    }

    /**
     * @param project:
     * @param classInfo:
     * @return java.lang.String
     * @author HXH
     * @description: 直接在项目中生成controller代码
     * @date 2024/5/23
     **/
    public static void generationControllerClass(Project project, ClassInfo classInfo) throws IOException {
        generationControllerClass(project, classInfo, null);
    }

    /**
     * @param packageName:
     * @param classInfo:
     * @author HXH
     * @description: 生成controller代码，并返回字符串
     * @date 2024/5/23
     **/
    public static String generationControllerClass(String packageName, ClassInfo classInfo) throws IOException {
        return generationControllerClass(null, classInfo, packageName);
    }

    private static String generationControllerClass(Project project, ClassInfo classInfo,
                                                    String packageName) throws IOException {
        if (project == null && StringUtils.isBlank(packageName)) {
            log.error("generationControllerClass中，project参数和packageName参数不能同时为空!");
            throw new RuntimeException("generationControllerClass中，project参数和packageName参数不能同时为空!");
        }
        boolean returnModel = false;
        if (project == null) {
            returnModel = true;
        }

        //页面配置
        ProjectTablePageConfig projectTablePageConfig = classInfo.getProjectTablePageConfig();

        String className = classInfo.getClassName();
        String classDesc = classInfo.getDesc();
        String serviceName = className + "Service";
        String serviceNameEntity = StringUtils.uncapitalize(serviceName);
        String classNameEntity = StringUtils.uncapitalize(className);

        String controllerName = className + "Controller";

        String controllerTempName = controllerName + ".Template";
        File tempClassFile;
        if (returnModel) {
            tempClassFile = File.createTempFile(controllerName, ".Template");
        } else {
            tempClassFile = GenUtil.newFile(project, "controller", controllerTempName);
        }

        StringBuilder importAddition = new StringBuilder();
        StringBuilder autowiredAddition = new StringBuilder();

        //先生成模板
        try {
            FileWriter fileWriter = new FileWriter(tempClassFile);
            BufferedWriter writer = new BufferedWriter(fileWriter);

            File template = new File(Constants.templatePathPrefix + "simple\\template\\controllerTemplate");
            BufferedReader br = new BufferedReader(new FileReader(template));
            String line;
            while ((line = br.readLine()) != null) {
                if (StringUtils.isNotBlank(line)) {
                    writer.write(line);
                }
                writer.newLine();
            }
            br.close();


            template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\listPage");
            br = new BufferedReader(new FileReader(template));
            while ((line = br.readLine()) != null) {
                ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
            }
            br.close();

            if ("1".equals(projectTablePageConfig.getShowAdd())) {
                template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\add");
                br = new BufferedReader(new FileReader(template));
                while ((line = br.readLine()) != null) {
                    ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                }
                br.close();
            }
            if ("1".equals(projectTablePageConfig.getShowUpdate())) {
                template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\update");
                br = new BufferedReader(new FileReader(template));
                while ((line = br.readLine()) != null) {
                    ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                }
                br.close();
            }
            if ("1".equals(projectTablePageConfig.getShowDelete())) {
                template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\delete");
                br = new BufferedReader(new FileReader(template));
                while ((line = br.readLine()) != null) {
                    ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                }
                br.close();
            }
            if ("1".equals(projectTablePageConfig.getShowBatchExport())) {
                template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\batchExport");
                br = new BufferedReader(new FileReader(template));
                while ((line = br.readLine()) != null) {
                    ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                }
                br.close();
            }
            if ("1".equals(projectTablePageConfig.getShowBatchAdd())) {
                template = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\batchImport");
                br = new BufferedReader(new FileReader(template));
                while ((line = br.readLine()) != null) {
                    ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                }
                br.close();
            }

            //加上addition\\controllerTemplateSplit文件下，与类名相同的文件夹下所有的文件，如addition\\controllerTemplateSplit\\BatchImportExportConfigController\\addition
            File additionFile = new File(Constants.templatePathPrefix + "simple\\template\\addition\\controllerTemplateSplit\\" + controllerName);
            if (additionFile.exists() && additionFile.isDirectory()) {
                File[] additionFiles = additionFile.listFiles();
                if (additionFiles != null && additionFiles.length > 0) {
                    for (File file : additionFiles) {
                        br = new BufferedReader(new FileReader(file));
                        while ((line = br.readLine()) != null) {
                            ProcessWriteLine.processPerLine(line, importAddition, autowiredAddition, writer);
                        }
                        br.close();
                    }
                }
            }

            writer.newLine();
            writer.write("}");

            writer.close();
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //临时模板2
        String controllerTempName2 = controllerName + ".Template2";
        File tempClassFile2;
        if (returnModel) {
            tempClassFile2 = File.createTempFile(controllerName, ".Template2");
        } else {
            tempClassFile2 = GenUtil.newFile(project, "controller", controllerTempName2);
        }
        Map<String, String> replaceWord = new HashMap<>();
        try {
            FileWriter fileWriter = new FileWriter(tempClassFile2);
            BufferedWriter writer = new BufferedWriter(fileWriter);

            File template = tempClassFile;
            BufferedReader br = new BufferedReader(new FileReader(template));
            String line;

            String checkExistStr = getCheckExist(classInfo);
            StringBuilder params = new StringBuilder();
            for (FieldName fieldName : classInfo.getIdNameList()) {
                params.append("@RequestParam ").append(fieldName.getJavaType()).append(" ").append(fieldName.getJavaName()).append(", ");
            }
            if (params.length() > 0) {
                params.deleteCharAt(params.length() - 2);
            }
            String deleteByIdParamWithType = params.toString();

            params.setLength(0);
            for (FieldName fieldName : classInfo.getIdNameList()) {
                params.append(fieldName.getJavaName()).append(", ");
            }
            if (params.length() > 0) {
                params.deleteCharAt(params.length() - 2);
            }
            String deleteByIdParam = params.toString();

            replaceWord.put("checkExist", checkExistStr);
            replaceWord.put("deleteByIdParamWithType", deleteByIdParamWithType);
            replaceWord.put("deleteByIdParam", deleteByIdParam);
            replaceWord.put("importAddition", importAddition.toString());
            replaceWord.put("autowiredAddition", autowiredAddition.toString());
            replaceWord.put("GroupId", returnModel ? packageName : project.getBackendProject().getProjectGroup());
            replaceWord.put("controllerName", controllerName);
            replaceWord.put("serviceNameEntity", serviceNameEntity);
            replaceWord.put("classNameEntity", classNameEntity);
            replaceWord.put("className", className);
            replaceWord.put("serviceName", serviceName);
            replaceWord.put("classDesc", classDesc);

            ProcessWriteLine processWriteLine = new ProcessWriteLine(replaceWord);
            while ((line = br.readLine()) != null) {
                processWriteLine.writeLine(line, writer);
            }
            br.close();
            writer.close();
            fileWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //处理重复的方法
        try {
            BufferedWriter writer;
            FileWriter fileWriter = null;
            StringWriter stringWriter = null;
            if (returnModel) {
                stringWriter = new StringWriter();
                writer = new BufferedWriter(stringWriter);
            } else {
                File classFile = GenUtil.newFile(project, "controller", controllerName);
                fileWriter = new FileWriter(classFile);
                writer = new BufferedWriter(fileWriter);
            }

            File template = tempClassFile2;
            BufferedReader br = new BufferedReader(new FileReader(template));
            String line;

            List<JavaClassMethod> methodList = ParseJavaMethod.parser(tempClassFile2.getAbsolutePath());
            List<JavaClassMethod> methodRepeatList = ParseJavaMethod.tagRepeatMethod(methodList);
            ProcessWriteLine processWriteLine = new ProcessWriteLine(replaceWord, methodList, methodRepeatList);
            int currentLine = 0;
            while ((line = br.readLine()) != null) {
                currentLine++;
                processWriteLine.writeLineWithRepeatMethod(line, writer, currentLine);
            }
            br.close();

            writer.close();
            if (fileWriter != null) {
                fileWriter.close();
            }

            String bakPath = tempClassFile.getAbsolutePath() + ".bak";
            File bakFile = new File(bakPath);
            if (tempClassFile.exists()) {
                tempClassFile.delete();
            }
            if (bakFile.exists()) {
                bakFile.delete();
            }
            bakPath = tempClassFile2.getAbsolutePath() + ".bak";
            bakFile = new File(bakPath);
            if (tempClassFile2.exists()) {
                tempClassFile2.delete();
            }
            if (bakFile.exists()) {
                bakFile.delete();
            }
            if (returnModel) {
                return stringWriter.toString();
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        return null;
    }

}
